﻿#include"pch.h"
#include "IPv4.h"
#include< iostream> 
#include< stdio.h> 
#include< stdlib.h>

struct  ipv4* Init()
{
	struct ipv4 *head = new  ipv4;
	struct ipv4 *p = head;
	cout << "请输入信息(输入Q或q退出)" << endl;


	cout << "源IP\t" << "目标IP\t" << "报文ID\t" << "长度\t" << "数据\t" << "结束位\t" << "偏移量\t" << endl;
	while (1)
	{
		//cout << "请继续输入（-1退出)" << endl;
		string s;
		cin >> s;

		if (s == "Q" || s == "q") { p->link = NULL; return head; }
		p->link = new ipv4;
		p = p->link;
		p->ip_src = s;
		cin >> p->ip_des >> p->id >> p->data >> p->length >> p->mf >> p->fo;
	}
	return head;
}


struct  ipv4* Input()
{

	/*"\t"*/
	struct ipv4 *head = new  ipv4;
	struct ipv4 *p = head;
	cout << "源IP\t" << "目标IP\t" << "报文ID\t" << "报文长度\t" << "数据\t\t" << "结束位\t" << "偏移量\t" << endl;
	p->link = new ipv4;
	p = p->link;
	cin >> p->ip_src >> p->ip_des >> p->id >> p->data >> p->length >> p->mf >> p->fo;
	p->link = NULL;
	return head;
}


void Recombine_Sort(struct ipv4 &l) //报文重组排序
{
	struct ipv4 *p = l.link, *pre;
	struct ipv4 *r = p->link;
	p->link = NULL;
	p = r;
	while (p != NULL)
	{
		r = p->link;
		pre = &l;
		while (pre->link != NULL && pre->link->fo < p->fo)
		{
			pre = pre->link;
		}
		if (pre != NULL)
		{
			p->link = pre->link;
			pre->link = p;
			p = r;
		}

	}
}

int min_fo(int a, int b)
{
	if (a < b)
		return a;
	else
		return b;
}

int merge(vector<struct ipv4> &arr/*in*/, vector<struct ipv4> &big_seg/*out*/) //小报文合并
{
	int count = 0;
	int sum_all = 0;
	int b = MIN;

	//big_seg[0].data = "";
	for (int i = 0; i < arr.size(); i++)
	{
		struct ipv4 *p = &arr[i];

		if (p->link != NULL)
		{
			p = p->link;

			big_seg[count].ip_des = p->ip_des;
			big_seg[count].ip_src = p->ip_src;


			big_seg[count].id = p->id;
			if (big_seg[0].data == "") {
				while (p)
				{
					if (p->fo * 8 - sum_all > 0)
					{
						big_seg[count].mf = 1;
						big_seg[count].fo = min(p->fo, b);
						b = big_seg[count].fo;
					}
					else
					{
						big_seg[count].mf = 0;
						big_seg[count].fo = 0;
					}


					big_seg[count].data += p->data;
					big_seg[count].length += p->length;
					sum_all += big_seg[count].length;

					p = p->link;
				}
			}
			else {
				if (p->fo * 8 - sum_all > 0)
				{
					big_seg[count].mf = 1;
					big_seg[count].fo = min(p->fo, b);
					b = big_seg[count].fo;
				}
				else
				{
					big_seg[count].mf = 0;
					big_seg[count].fo = 0;
				}


				big_seg[count].data = p->data + big_seg[count].data;
				big_seg[count].length += p->length;
				sum_all += big_seg[count].length;

				p = p->link;
			}
			count++;
		}
	}
	return count;
}

void Output(struct ipv4* head)
{

	cout << "源IP\t" << "目标IP\t" << "报文ID\t" << "长度\t" << "数据\t\t" << "结束位\t" << "偏移量\t" << endl;
	struct ipv4 *p = head;
	p = p->link;
	while (p != NULL)
	{
		cout << p->ip_src << "\t" << p->ip_des << "\t" << p->id << "\t" << p->length << "\t" << p->data << "\t\t" << p->mf << "\t"
			<< p->fo << endl;
		p = p->link;
	}
}

void randperm(vector<struct ipv4> &temp)//报文初始化
{
	int count = 0;
	char *str = (char *)malloc(sizeof(char) * 20);
	srand((int)time(0));
	int des = rand();
	string ip_des = Creat_IP(str, 8, rand());
	for (int i = 0; i < temp.size() / SEGNUM; i++)
	{

		string ip_src = Creat_IP(str, 8, rand());

		for (int j = 0; j < SEGNUM; j++)
		{
			temp[j + i * SEGNUM].ip_des = ip_des;
			temp[j + i * SEGNUM].ip_src = ip_src;
			temp[j + i * SEGNUM].data = Create_Data(str, 2, rand());
			temp[j + i * SEGNUM].id = i;
			temp[j + i * SEGNUM].fo = j * 125;
			if (j == SEGNUM - 1)
			{
				temp[j + i * SEGNUM].length = rand() % temp[SEGNUM * i].length;
				temp[j + i * SEGNUM].mf = 0;
			}
			else
			{
				temp[j + i * SEGNUM].length = 1000;
				temp[j + i * SEGNUM].mf = 1;
			}

		}
	}
	random_shuffle(temp.begin(), temp.end());//随机打乱vector中的数据。
}

char* Create_Data(char *str, const int len, unsigned zz)  //随机生成数据内容
{
	srand(zz);
	int i;
	for (i = 0; i < len; i++)
	{
		switch ((rand() % 3))
		{
		case 1:
			str[i] = 'A' + rand() % 26;
			break;
		case 2:
			str[i] = 'a' + rand() % 26;
			break;
		default:
			str[i] = '0' + rand() % 10;
			break;
		}
	}
	str[i] = '\0';
	return str;
}

char* Creat_IP(char *str, const int len, unsigned zz)  //随机生成ip地址
{
	srand(zz);
	int i;
	for (i = 0; i < len; i++)
	{
		str[i] = '0' + rand() % 10;
	}
	str[i] = '\0';
	return str;
}

void Save(vector<struct ipv4>arr, char a, int count)  //将数组写到文件中
{
	string path = "D:\\DensityData";
	path += a;
	path += ".txt";
	ofstream outfile(path);
	if (!outfile.is_open())
	{
		cout << " 文件打开失败" << endl;
		exit(1);
	}
	outfile << "源IP" << "\t" << "目的IP" << "\t" << "报文ID" << "\t" << "长度" << "\t" << "数据" << "\t"
		<< "结束位" << "\t" << "偏移量" << endl;
	int sum = 0;
	for (int i = 0; i < count; i++)
	{
		sum++;
		outfile << arr[i].ip_src << "\t" << arr[i].ip_des << "\t" << arr[i].id << "\t" << arr[i].length << "\t"
			<< arr[i].data << "\t" << arr[i].mf << "\t" << arr[i].fo << endl;
	}
	cout << sum << endl;
	outfile.close();
}

void Connect(vector<struct ipv4>&arr/*in*/, struct ipv4 *head/*out*/)//形成链表
{
	head->link = &arr[0];
	for (int i = 0; i < arr.size() - 1; i++)
	{
		arr[i].link = &arr[i + 1];
	}
	arr[arr.size() - 1].link = NULL;
}



void Recombine(vector<struct ipv4> &arr, struct ipv4 *head)//多流重组
{

	struct ipv4 *p = head;
	p = p->link;
	while (p != NULL)
	{
		map<int, bool>::iterator iter;
		iter = date.find(p->id);
		if (iter != date.end())
		{
			p = p->link;
			continue;
		}
		if (p->fo == 0)
		{
			/*需要开始计时*/
			timearr[p->id] = clock();
		}

		struct ipv4 *q = p;
		/*这里异常报文处理*/
		/*功能：判断是否为异常报文，并返回分片/报文头指针
		说明：返回值为0时，表示收到的不是分片，直接返回大报文；为1，无异常；<0，
		有异常(-1，该分片全部被包含，舍弃；-2，分片部分包含,对分片作截断，-3该分片包含其他分片,-4被舍弃，为1时，表示收到的无重叠问题
		*/
		int k = Error_Detect(arr, q);
		if (k == 0) {/*停止一下它的计时器*/ }
		else if (k == -1 || k == -4) { p = p->link; continue; }//q被舍弃了
		else {

			//差一个计时，判断是否超时，超时则不链接，并且释放超时报文所有分片
			if ((double)(clock() - timearr[p->id]) / CLOCKS_PER_SEC > MYTIME)
			{

				cout << p->ip_src << "\t" << p->ip_des << "\t" << p->id << "\t" << p->length << "\t"
					<< p->data << "\t" << p->mf << "\t" << p->fo << "\t接收超时！" << endl;

				date.insert(pair<int, bool>(p->id, true));
				Destory(b[p->id]);
				p = p->link;
				continue;
			}
			head->link = p->link;
			p = p->link;
			q->link = NULL;//把当前分片从链表中取下
			Recieve(*q, arr[q->id]); //顺序连起来（无序链在对应流的最末尾
			if (Finish(arr[q->id]))  //判断是否收齐
			{

				cout << q->ip_src << "\t" << q->ip_des << "\t" << q->id << "\t" << q->length << "\t"
					<< q->data << "\t" << q->mf << "\t" << q->fo << "\t接收成功！" << endl;

				Recombine_Sort(arr[q->id]); //单流重组

			}
		}
	}
}

void Destory(struct  ipv4 &head)
{
	if (NULL == head.link) //表空
	{
		return;
	}
	struct ipv4 *p = head.link;
	while (head.link != NULL)
	{
		head.link = p->link;
		struct ipv4 *temp = p;
		p = p->link;
		temp->link = NULL;
	}
}

void Recieve(struct ipv4 &data, struct ipv4 &head)//接收报文
{
	struct ipv4 *p = &head;
	while (p->link != NULL)
	{
		p = p->link;
	}
	p->link = &data;
}

bool Finish(struct ipv4 list)/*判断是否收齐*/
{
	struct ipv4 *p = &list;
	int sum = 0;
	p = p->link;
	int total = 0;
	while (p)
	{
		sum += p->length;
		if (p->mf == 0)
		{
			total = p->length + p->fo * 8;
		}
		p = p->link;
	}
	if (sum == total)
	{
		return true;
	}
	else
	{
		return false;
	}
}

int Error_Detect(vector<struct ipv4>&arr/*in*/, struct ipv4* segment/*in*/)  //异常类型检测
{
	if (NULL == segment)return -1;
	struct ipv4* tempseg = segment;
	//报文不是分片，直接返回大报文
	if (tempseg->fo == 0 && tempseg->mf == 0)return 0;

	//非尾片，数据长度非8字节整数倍、舍弃
	if (segment->mf != 0 && segment->length % 8 != 0)return -4;

	//与其他分片有包含或重叠关系
	//struct ipv4* temp = &arr[tempseg->id];

	struct ipv4* temp = &arr[0];


	int k = Is_Contain(temp, tempseg);
	return k;
}

int Is_Contain(struct ipv4* head/*in*/, struct ipv4* seg/*in*/)
{
	int start = seg->fo * 8, end = seg->fo * 8 + seg->length - 1;
	struct ipv4* thead = head->link;
	int find = 1;
	//从第一个结点开始遍历
	while (NULL != thead)
	{
		int s = thead->fo * 8, e = thead->fo * 8 + thead->length - 1;
		// 包含分片前端
		if (s < start&&start < e && e < end)
		{
			Devide(thead, seg);
			find = -2;
		}
		//包含分片后端
		else if (start < s&&s < end&&end < e)
		{
			Devide(seg, thead);
			find = -2;
		}
		// 分片全部被包含
		else if (s <= start && end <= e)
		{
			return -1;
		}
		//分片包含其他分片
		else if (start <= s && e <= end)
		{
			//释放其他分片
			//找到链接此分片的前一分片
			struct ipv4* q = head, *q2 = thead->link;
			while (q->link != thead)q = q->link;
			//从链表中取下此分片
			q->link = q2;
			//释放此分片空间
			thead = q;
			find = -3;
		}
		thead = thead->link;
	}
	return find;
}

int Devide(struct ipv4* p1/*in,out*/, struct ipv4* p2/*in*/)
{
	p1->length = (p2->fo - p1->fo) * 8;
	p1->data = p1->data.substr(0, p1->length);
	return 0;
}

void SubStep()
{
	struct ipv4* temp;
	vector<struct ipv4>arr(1), ret(1);
	cout << "输入报文作为初始报文片(id为0）" << endl;
	vector<struct ipv4> start(1);
	struct ipv4* head = Input();
	start[0] = *(head);
	struct ipv4* t = head->link;
	struct ipv4* q = head->link;
	cout << "初始化完成" << endl;

	//单流分片重组验收接口
	int choice = 1;
	while (choice)
	{

		cout << "请输入报文：" << endl;
		temp = Input();

		//arr[0] = *temp;
		cout << "正在判断是否异常..." << endl;

		struct ipv4* p = temp->link;
		if (NULL != p)
		{

			int j = Error_Detect(start, p);
			if (j == 0)
			{
				cout << "收到的不是分片！" << endl;
				cout << "继续输入？（1继续,0退出）" << endl;
				cin >> choice;
			}

			else if (j == 1)
			{
				cout << "无异常！" << endl;

				cout << "初始化完成，正在重组..." << endl << endl;
				//arr[0] = *(head);

				t->link = temp->link;
				head->link->link = temp->link;
				t = t->link;
				t->link = NULL;
				arr[0] = *(head);
				Recombine_Sort(arr[0]);

				while (t->link != NULL) {
					t = t->link;
				}
				merge(arr, ret);

				temp->link = &ret[0];
				cout << "重组后的报文为：" << endl;
				Output(temp);

				start[0] = *(temp);
				head = temp;
				cout << "继续输入？（1继续,0退出）" << endl;
				cin >> choice;
			}

			else if (j == -1)
			{
				cout << "该分片被已有分片全部包含，舍弃！" << endl;
				cout << "继续输入？（1继续,0退出）" << endl;
				cin >> choice;

			}


			else if (j == -2)
			{
				cout << "该分片与其他有重叠，截断后，异常分片：" << endl;


				cout << "源IP\t" << "目标IP\t" << "报文ID\t" << "长度\t" << "数据\t" << "结束位\t" << "偏移量\t" << endl;
				cout << p->ip_src << "\t" << p->ip_des << "\t" << p->id << "\t" << p->length << "\t"
					<< p->data << "\t" << p->mf << "\t" << p->fo << endl;

				cout << "其他正常分片：" << endl;
				Output(head);

				cout << "继续输入？（1继续,0退出）" << endl;
				cin >> choice;

			}
			else if (j == -3)
			{
				cout << "该分片包含了其他已有分片，已释放被包含分片!" << endl;
				cout << "目前其他正常分片：" << endl;
				Output(head);

				cout << "继续输入？（1继续,0退出）" << endl;
				cin >> choice;

			}
			else if (j == -4)
			{
				cout << "该分片非尾分片且数据长度非8整数倍,已被丢弃！" << endl;

				cout << "继续输入？（1继续,0退出）" << endl;
				cin >> choice;

			}

		}

	}
}

void SeQuence()
{
	int choice = 1;
	while (choice)
	{
		cout << "请构造报文分片" << endl;

		struct ipv4* head = Init();
		vector<struct ipv4>arr(1), ret(1);
		arr[0] = *head;

		cout << "初始化完成，正在重组..." << endl;

		Recombine_Sort(*head);
		merge(arr, ret);

		head->link = &ret[0];

		cout << "重组后的报文为：" << endl;
		Output(head);


		cout << "继续输入？（1继续,0退出）" << endl;
		cin >> choice;

	}
}

void MultiThread()
{
	vector<struct ipv4> a(SEGNUM*MESNUM);
	randperm(a);

	Save(a, '1', a.size());
	struct ipv4 h;
	struct ipv4 *head = &h;
	Connect(a, head);
	Recombine(b, head);

	vector<struct ipv4> c(b);
	int count = merge(b, c);
	cout << "成功重组如下：" << endl;
	for (int i = 0; i < count; i++)
	{
		cout << c[i].ip_src << "\t" << c[i].ip_des << "\t" << c[i].id << "\t" << c[i].length << "\t"
			<< c[i].data << "\t" << c[i].mf << "\t" << c[i].fo << "\t接收成功！" << endl;
	}
	Save(c, '2', count);
}

int Menu()
{
	int choice;

	cout << "1.单流分步重组" << endl;
	cout << "2.单流连续重组" << endl;
	cout << "3.多流连续重组" << endl;
	cout << "请选择操作序号：" << endl;
	cin >> choice;
	return choice;
}

int main()
{
	int flag = 1;
	while (flag)
	{
		int choose = Menu();
		switch (choose)
		{
		case 1: SubStep(); break;
		case 2: SeQuence(); break;
		case 3:
			cout << "源IP\t" << "目标IP\t" << "报文ID\t" << "长度\t" << "数据\t" << "结束位\t" << "偏移量\t" << endl;
			MultiThread(); break;
		default: break;
		}
		cout << "是否继续测试？（是：1，否：0）" << endl;
		cin >> flag;
		system("cls");
	}

	system("pause");
	return 0;
}